/*
* @(#)DrawApplet.java 5.1
*
*/
package CH.ifa.draw.applet;
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Choice;
import java.awt.Color;
import java.awt.GraphicsEnvironment;
import java.awt.Label;
import java.awt.Panel;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.net.URL;
import java.util.StringTokenizer;
import CH.ifa.draw.figures.AttributeFigure;
import CH.ifa.draw.figures.GroupCommand;
import CH.ifa.draw.figures.PolyLineFigure;
import CH.ifa.draw.figures.UngroupCommand;
import CH.ifa.draw.framework.Drawing;
import CH.ifa.draw.framework.DrawingEditor;
import CH.ifa.draw.framework.DrawingView;
import CH.ifa.draw.framework.Figure;
import CH.ifa.draw.framework.FigureEnumeration;
import CH.ifa.draw.framework.Tool;
import CH.ifa.draw.standard.BufferedUpdateStrategy;
import CH.ifa.draw.standard.ChangeAttributeCommand;
import CH.ifa.draw.standard.DeleteCommand;
import CH.ifa.draw.standard.DuplicateCommand;
import CH.ifa.draw.standard.SelectionTool;
import CH.ifa.draw.standard.SimpleUpdateStrategy;
import CH.ifa.draw.standard.StandardDrawing;
import CH.ifa.draw.standard.StandardDrawingView;
import CH.ifa.draw.standard.ToolButton;
import CH.ifa.draw.util.ColorMap;
import CH.ifa.draw.util.CommandButton;
import CH.ifa.draw.util.CommandChoice;
import CH.ifa.draw.util.Filler;
import CH.ifa.draw.util.Iconkit;
import CH.ifa.draw.util.PaletteButton;
import CH.ifa.draw.util.PaletteLayout;
import CH.ifa.draw.util.PaletteListener;
import CH.ifa.draw.util.StorableInput;
/**
* DrawApplication defines a standard presentation for
* a drawing editor that is run as an applet. The presentation is
* customized in subclasses.<p>
* Supported applet parameters: <br>
* <i>DRAWINGS</i>: a blank separated list of drawing names that is
* shown in the drawings choice.
*/
public class DrawApplet
extends Applet
implements DrawingEditor, PaletteListener {
transient private Drawing fDrawing;
transient private Tool fTool;
transient private StandardDrawingView fView;
transient private ToolButton fDefaultToolButton;
transient private ToolButton fSelectedToolButton;
transient private boolean fSimpleUpdate;
transient private Button fUpdateButton;
transient private Choice fFrameColor;
transient private Choice fFillColor;
//transient private Choice fTextColor;
transient private Choice fArrowChoice;
transient private Choice fFontChoice;
transient private Thread fSleeper;
private Iconkit fIconkit;
static String fgUntitled = "untitled";
private static final String fgDrawPath = "/CH/ifa/draw/";
public static final String IMAGES = fgDrawPath + "images/";
/**
* Initializes the applet and creates its contents.
*/
public void init() {
fIconkit = new Iconkit(this);
setLayout(new BorderLayout());
fView = createDrawingView();
Panel attributes = createAttributesPanel();
createAttributeChoices(attributes);
add("North", attributes);
Panel toolPanel = createToolPalette();
createTools(toolPanel);
add("West", toolPanel);
add("Center", fView);
Panel buttonPalette = createButtonPanel();
createButtons(buttonPalette);
add("South", buttonPalette);
initDrawing();
setBufferedDisplayUpdate();
setupAttributes();
}
/*
* Gets the iconkit to be used in the applet.
*/
/**** not sure whether this will still be needed on 1.1 enabled browsers
protected Iconkit iconkit() {
if (fIconkit == null) {
startSleeper();
loadAllImages(this); // blocks until images loaded
stopSleeper();
}
return fIconkit;
} */
/**
* Creates the attributes panel.
*/
protected Panel createAttributesPanel() {
Panel panel = new Panel();
panel.setLayout(new PaletteLayout(2, new Point(2, 2), false));
return panel;
}
/**
* Creates the attribute choices. Override to add additional
* choices.
*/
protected void createAttributeChoices(Panel panel) {
panel.add(new Label("Fill"));
fFillColor = createColorChoice("FillColor");
panel.add(fFillColor);
//panel.add(new Label("Text"));
//fTextColor = createColorChoice("TextColor");
//panel.add(fTextColor);
panel.add(new Label("Pen"));
fFrameColor = createColorChoice("FrameColor");
panel.add(fFrameColor);
panel.add(new Label("Arrow"));
CommandChoice choice = new CommandChoice();
fArrowChoice = choice;
choice.addItem(
new ChangeAttributeCommand(
"none",
"ArrowMode",
new Integer(PolyLineFigure.ARROW_TIP_NONE),
fView));
choice.addItem(
new ChangeAttributeCommand(
"at Start",
"ArrowMode",
new Integer(PolyLineFigure.ARROW_TIP_START),
fView));
choice.addItem(
new ChangeAttributeCommand(
"at End",
"ArrowMode",
new Integer(PolyLineFigure.ARROW_TIP_END),
fView));
choice.addItem(
new ChangeAttributeCommand(
"at Both",
"ArrowMode",
new Integer(PolyLineFigure.ARROW_TIP_BOTH),
fView));
panel.add(fArrowChoice);
panel.add(new Label("Font"));
fFontChoice = createFontChoice();
panel.add(fFontChoice);
}
/**
* Creates the color choice for the given attribute.
*/
protected Choice createColorChoice(String attribute) {
CommandChoice choice = new CommandChoice();
for (int i = 0; i < ColorMap.size(); i++)
choice.addItem(
new ChangeAttributeCommand(
ColorMap.name(i),
attribute,
ColorMap.color(i),
fView));
return choice;
}
/**
* Creates the font choice. The choice is filled with
* all the fonts supported by the toolkit.
*/
protected Choice createFontChoice() {
CommandChoice choice = new CommandChoice();
String fonts[] =
GraphicsEnvironment
.getLocalGraphicsEnvironment()
.getAvailableFontFamilyNames();
for (int i = 0; i < fonts.length; i++)
choice.addItem(
new ChangeAttributeCommand(
fonts[i],
"FontName",
fonts[i],
fView));
return choice;
}
/**
* Creates the buttons panel.
*/
protected Panel createButtonPanel() {
Panel panel = new Panel();
panel.setLayout(new PaletteLayout(2, new Point(2, 2), false));
return panel;
}
/**
* Creates the buttons shown in the buttons panel. Override to
* add additional buttons.
* @param panel the buttons panel.
*/
protected void createButtons(Panel panel) {
panel.add(new Filler(24, 20));
Choice drawingChoice = new Choice();
drawingChoice.addItem(fgUntitled);
String param = getParameter("DRAWINGS");
if (param == null)
param = "";
StringTokenizer st = new StringTokenizer(param);
while (st.hasMoreTokens())
drawingChoice.addItem(st.nextToken());
// offer choice only if more than one
if (drawingChoice.getItemCount() > 1)
panel.add(drawingChoice);
else
panel.add(new Label(fgUntitled));
drawingChoice.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
loadDrawing((String) e.getItem());
}
}
});
panel.add(new Filler(6, 20));
Button button;
button = new CommandButton(new DeleteCommand("Delete", fView));
panel.add(button);
button = new CommandButton(new DuplicateCommand("Duplicate", fView));
panel.add(button);
button = new CommandButton(new GroupCommand("Group", fView));
panel.add(button);
button = new CommandButton(new UngroupCommand("Ungroup", fView));
panel.add(button);
button = new Button("Help");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
showHelp();
}
});
panel.add(button);
fUpdateButton = new Button("Simple Update");
fUpdateButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
if (fSimpleUpdate)
setBufferedDisplayUpdate();
else
setSimpleDisplayUpdate();
}
});
// panel.add(fUpdateButton); // not shown currently
}
/**
* Creates the tools palette.
*/
protected Panel createToolPalette() {
Panel palette = new Panel();
palette.setLayout(new PaletteLayout(2, new Point(2, 2)));
return palette;
}
/**
* Creates the tools. By default only the selection tool is added.
* Override this method to add additional tools.
* Call the inherited method to include the selection tool.
* @param palette the palette where the tools are added.
*/
protected void createTools(Panel palette) {
Tool tool = createSelectionTool();
fDefaultToolButton =
createToolButton(IMAGES + "SEL", "Selection Tool", tool);
palette.add(fDefaultToolButton);
}
/**
* Creates the selection tool used in this editor. Override to use
* a custom selection tool.
*/
protected Tool createSelectionTool() {
return new SelectionTool(view());
}
/**
* Creates a tool button with the given image, tool, and text
*/
protected ToolButton createToolButton(
String iconName,
String toolName,
Tool tool) {
return new ToolButton(this, iconName, toolName, tool);
}
/**
* Creates the drawing used in this application.
* You need to override this method to use a Drawing
* subclass in your application. By default a standard
* Drawing is returned.
*/
protected Drawing createDrawing() {
return new StandardDrawing();
}
/**
* Creates the drawing view used in this application.
* You need to override this method to use a DrawingView
* subclass in your application. By default a standard
* DrawingView is returned.
*/
protected StandardDrawingView createDrawingView() {
return new StandardDrawingView(this, 410, 370);
}
/**
* Handles a user selection in the palette.
* @see PaletteListener
*/
public void paletteUserSelected(PaletteButton button) {
ToolButton toolButton = (ToolButton) button;
setTool(toolButton.tool(), toolButton.name());
setSelected(toolButton);
}
/**
* Handles when the mouse enters or leaves a palette button.
* @see PaletteListener
*/
public void paletteUserOver(PaletteButton button, boolean inside) {
if (inside)
showStatus(((ToolButton) button).name());
else
showStatus(fSelectedToolButton.name());
}
/**
* Gets the current drawing.
* @see DrawingEditor
*/
public Drawing drawing() {
return fDrawing;
}
/**
* Gets the current tool.
* @see DrawingEditor
*/
public Tool tool() {
return fTool;
}
/**
* Gets the current drawing view.
* @see DrawingEditor
*/
public DrawingView view() {
return fView;
}
/**
* Sets the default tool of the editor.
* @see DrawingEditor
*/
public void toolDone() {
setTool(fDefaultToolButton.tool(), fDefaultToolButton.name());
setSelected(fDefaultToolButton);
}
/**
* Handles a change of the current selection. Updates all
* menu items that are selection sensitive.
* @see DrawingEditor
*/
public void selectionChanged(DrawingView view) {
setupAttributes();
}
private void initDrawing() {
fDrawing = createDrawing();
fView.setDrawing(fDrawing);
toolDone();
}
private void setTool(Tool t, String name) {
if (fTool != null)
fTool.deactivate();
fTool = t;
if (fTool != null) {
showStatus(name);
fTool.activate();
}
}
private void setSelected(ToolButton button) {
if (fSelectedToolButton != null)
fSelectedToolButton.reset();
fSelectedToolButton = button;
if (fSelectedToolButton != null)
fSelectedToolButton.select();
}
protected void loadDrawing(String param) {
if (param == fgUntitled) {
fDrawing.release();
initDrawing();
return;
}
String filename = getParameter(param);
if (filename != null)
readDrawing(filename);
}
private void readDrawing(String filename) {
toolDone();
String type = guessType(filename);
if (type.equals("storable"))
readFromStorableInput(filename);
else if (type.equals("serialized"))
readFromObjectInput(filename);
else
showStatus("Unknown file type");
}
private void readFromStorableInput(String filename) {
try {
URL url = new URL(getCodeBase(), filename);
InputStream stream = url.openStream();
StorableInput input = new StorableInput(stream);
fDrawing.release();
fDrawing = (Drawing) input.readStorable();
fView.setDrawing(fDrawing);
}
catch (IOException e) {
initDrawing();
showStatus("Error:" + e);
}
}
private void readFromObjectInput(String filename) {
try {
URL url = new URL(getCodeBase(), filename);
InputStream stream = url.openStream();
ObjectInput input = new ObjectInputStream(stream);
fDrawing.release();
fDrawing = (Drawing) input.readObject();
fView.setDrawing(fDrawing);
}
catch (IOException e) {
initDrawing();
showStatus("Error: " + e);
}
catch (ClassNotFoundException e) {
initDrawing();
showStatus("Class not found: " + e);
}
}
private String guessType(String file) {
if (file.endsWith(".draw"))
return "storable";
if (file.endsWith(".ser"))
return "serialized";
return "unknown";
}
private void setupAttributes() {
Color frameColor =
(Color) AttributeFigure.getDefaultAttribute("FrameColor");
Color fillColor =
(Color) AttributeFigure.getDefaultAttribute("FillColor");
// Color textColor =
// (Color) AttributeFigure.getDefaultAttribute("TextColor");
Integer arrowMode =
(Integer) AttributeFigure.getDefaultAttribute("ArrowMode");
String fontName =
(String) AttributeFigure.getDefaultAttribute("FontName");
FigureEnumeration k = fView.selectionElements();
while (k.hasMoreElements()) {
Figure f = k.nextFigure();
frameColor = (Color) f.getAttribute("FrameColor");
fillColor = (Color) f.getAttribute("FillColor");
// textColor = (Color) f.getAttribute("TextColor");
arrowMode = (Integer) f.getAttribute("ArrowMode");
fontName = (String) f.getAttribute("FontName");
}
fFrameColor.select(ColorMap.colorIndex(frameColor));
fFillColor.select(ColorMap.colorIndex(fillColor));
//fTextColor.select(ColorMap.colorIndex(textColor));
if (arrowMode != null)
fArrowChoice.select(arrowMode.intValue());
if (fontName != null)
fFontChoice.select(fontName);
}
protected void setSimpleDisplayUpdate() {
fView.setDisplayUpdate(new SimpleUpdateStrategy());
fUpdateButton.setLabel("Simple Update");
fSimpleUpdate = true;
}
protected void setBufferedDisplayUpdate() {
fView.setDisplayUpdate(new BufferedUpdateStrategy());
fUpdateButton.setLabel("Buffered Update");
fSimpleUpdate = false;
}
/**
* Shows a help page for the applet. The URL of the help
* page is derived as follows: codeBase+appletClassname+Help.html"
*/
protected void showHelp() {
try {
String appletPath = getClass().getName().replace('.', '/');
URL url = new URL(getCodeBase(), appletPath + "Help.html");
getAppletContext().showDocument(url, "Help");
}
catch (IOException e) {
showStatus("Help file not found");
}
}
/**
* *** netscape browser work around ***
*/
private void startSleeper() {
if (fSleeper == null)
fSleeper = new SleeperThread(this);
fSleeper.start();
}
private void stopSleeper() {
if (fSleeper != null)
fSleeper.stop();
}
}